home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UTIL / MEMORY / OLD / MEM208SRC / FSLib / doc / FSinC < prev    next >
Text File  |  1993-04-02  |  13KB  |  276 lines

  1. Making a Filing System for RISC OS in C
  2. =======================================
  3.  
  4. Author: Jonathan Roach
  5. History:
  6.   19-Feb-90: 0.00: started.
  7.  
  8. Summary
  9. -------
  10.  
  11. This document should describe the files contained and how to use them to
  12. make a RISC OS filing system written in C.
  13.  
  14.  
  15. Introduction
  16. ------------
  17.  
  18. The files contained here are a collection of files extracted from the NFS
  19. implementation written in Acorn. They make up the essential elements of
  20. interfacing C to FileSwitch in order to write a filing system. First, I
  21. shall describe, in recipe form, how to take the supplied files and to make
  22. them into a filing system. After that I shall describe how the interfacing
  23. mechanism works in greater technical depth.
  24.  
  25. Before you start writing a filing system for RISC OS, in C you should have
  26. the following tools available:
  27.  
  28. cc      The C compiler. Version 3.00 is required.
  29. ObjAsm  The object module assembler.
  30. link    The linker.
  31. cmhg    The C module header generator.
  32. amu     The make utility.
  33.  
  34. These come with C release 3.00.
  35.  
  36. I shall assume you have all the tools supplied with RISC OS, and that you
  37. have a copy of the RISC OS Programmers' Reference Manual to hand.
  38.  
  39.  
  40. The Files Supplied
  41. ------------------
  42.  
  43. amu.MakeFile    This is an amu control file to make DummyFS. It relies on
  44.                 CLib$Path being set to the directory containing the CLib
  45.                 headers and the stubs for the C library.
  46. asm.allerrs     This contains all the RISC OS error blocks which your filing
  47.                 system can generate. The reason the error blocks have been
  48.                 defined in assembler is to keep the memory wastage down.
  49. asm.Interface   Here is where most of the nasty gubbins of interfacing C to
  50.                 FileSwitch lurks. Its job is to pack the parameters passed
  51.                 by FileSwitch into a form that is easy for C to handle and
  52.                 to set flags that FileSwitch requires on exit from your
  53.                 filing system.
  54. asm.RMInfo      This is here to provide the base address of your filing
  55.                 system module. The address is available at link time as the
  56.                 variable Image$$RO$$Base, but, as this isn't a valid C
  57.                 variable name a small piece of assembler is needed to tidy
  58.                 that up.
  59. c.modulewrap    This is where the wrapping to turn your C into a filing
  60.                 system module sits. Its job is to give you a skeleton to
  61.                 work with when writing your filing system.
  62. c._Args         This provides the fsentry_args function.
  63. c._Close        This provides the fsentry_close function.
  64. c._File         This provides the fsentry_file function.
  65. c._Func         This provides the fsentry_func function.
  66. c._GBPB         This provides the fsentry_GBPB function.
  67. c._GetBytes     This provides the fsentry_GetBytes function.
  68. c._Open         This provides the fsentry_Open function.
  69. c._PutBytes     This provides the fsentry_PutBytes function.
  70. cmhg.nfscmhg    This is the cmhg (C Module Header Generator) source. Its job
  71.                 is to define the name of the module, the commands it takes
  72.                 and the names of any service call or interupt handlers you
  73.                 need.
  74. doc.FSinC       This document.
  75. DummyFS         A file whose only job is to be date stamped once DummyFS has
  76.                 been made successfully.
  77. h.allerrs       This declares the error blocks defined in asm.allerrs.
  78. h.Consts        This contains the C constants.
  79. h.DummyFS       This includes all headers used for making DummyFS.
  80. h.fsentries     This declares the filing system entry points in terms of C
  81.                 functions. The names of the functions declared in this file
  82.                 are assumed by asm.interface. The types used in this file
  83.                 can be found in h.veneers.
  84. h.Interface     This is the C header for asm.Interface.
  85. h.modulewrap    This declares the extern functions in c.modulewrap.
  86. h.RMInfo        This declares the variable defined in asm.RMInfo.
  87. h.Statics       This declares the static variables used by DummyFS.
  88. h.veneers       This defines the enums and types for the file system entry
  89.                 points.
  90. lnk.DummyFS     This is the link control file for DummyFS.
  91. Make            This obey file calls amu to make DummyFS with some useful
  92.                 options.
  93.  
  94.  
  95. Making a filing system
  96. ----------------------
  97.  
  98. There are  steps when making a filing system:
  99.  
  100. 1) Decide what its going to do. This may sound silly, but knowing what
  101. you're going to write is important because, if you don't know what you're
  102. going to write, then you don't know when you've written it! As a general
  103. rule for RISC OS filing systems, make it feel like other RISC OS filing
  104. systems as much as possible. Of course, you can skip over the mindless
  105. restrictions such as limited file name lengths, but do keep the essentials
  106. the same. These are:
  107.         a) The directory separator is a .
  108.         b) A file path, when passed to your filing system has had the file
  109.                 system name stripped. Suppose the full path the user gave
  110.                 was myfs#mything::HardDisc4.$.mydir.myfile then your filing
  111.                 system would get :HardDisc4.$.mydir.myfile which you must
  112.                 parse yourself and mything as the special field. The
  113.                 syntax :<disc>.<rest of path> should be followed,
  114.                 substituting <disc> for whatever corresponds to <disc> on
  115.                 your filing system.
  116.         c) Other features which are given in the PRM.
  117. The non-essentials, but highly desirables are support for:
  118.         a) All the 'root directories':
  119.                 $       <disc> root directory.
  120.                 @       current directory.
  121.                 &       user root directory
  122.                 %       library directory
  123.                 \       previously selected directory
  124.         b) A large collection of *-commands (see adfs's commands).
  125.  
  126. 2) Think about how to organise your filing system internally. Sort out what
  127. data structures you are going to need, and what common routines it would be
  128. nice to have around. At this stage leafing through the PRM (Programmers'
  129. Reference Manual) on writing your own filing system is a good idea.
  130.  
  131. 3) Start filling in the gaps in the supplied routines. I would suggest
  132. calling routines for the fsentries with many options (fsentry_func is the
  133. worst). Start with the routines which are easiest to test first, such as
  134. fsentry_func 3 (examine current directory) to build up confidence. 
  135.  
  136.  
  137. In amu.MakeFile:
  138.         Update this as more headers are included and more C files are
  139.                 added.
  140.  
  141. In asm.Allerrs:
  142.         Put your error blocks here. Note the error numbers in the supplied
  143.         asm.allerrs correspond to NFS and should be changed. When choosing
  144.         an error number try to match it to a similar error generated by
  145.         ADFS. This enables programs doing file operations to take acount
  146.         of errors generated by several filing systems. For example, the
  147.         disc full sort of error occurs in most filing systems. For ADFS
  148.         the error number is 0x000108C6 and for NFS it is 0x000121C6 where
  149.         only the 5th and 6th digits have changed for the filing system
  150.         number.
  151.  
  152. In c.ModuleWrap:
  153.         Fill in your SWI handling or junk the SWI handler routine if you
  154.                 don't have any SWIs.
  155.         Fill in the finalisation code (if any).
  156.         Fill in your filing system's name in declare_dummyfs.
  157.         Fill in your filing system's initialisation.
  158.         Fill in any other service calls you want to intercept.
  159.         Fill in any extra commands you want to process.
  160.  
  161. In c.Statics:
  162.         Fill in the static data you will need here. Keeping this small will
  163.         tend to make your code more reliable.
  164.  
  165. In c._<thing>:
  166.         The main part of your filing system sits in these. These are the
  167.         fsentry points which FileSwitch calls.
  168.  
  169. In cmhg.dummycmhg:
  170.         Fill in the strings, swis and commands appropriate to your filing
  171.         system.
  172.  
  173. In h.Allerrs:
  174.         Declare the error blocks in asm.Allerrs here.
  175.  
  176. In h.Consts:
  177.         Fill in your constants here. You will need to change these
  178.         constants for your filing system:
  179.                 FilingSystemName
  180.                 Information_Word
  181.  
  182. In h.DummyFS:
  183.         #include into this any other headers you need.
  184.  
  185. In h.Statics:
  186.         Declare the statics defined in c.Statics.
  187.  
  188. In lnk.DummyFS:
  189.         Add any extra files you need to link in in here.
  190.  
  191. All other files should be left alone, although reading through h.veneers is
  192. essential when picking apart the parameters passed to you by FileSwitch and
  193. reassembling them to pass back.
  194.  
  195. In general, bare in mind that you are guaranteed only 1k of stack. This
  196. means you must not have any large auto variables nor can you recurse safely.
  197. Compile with the -zM and -zps0 options. These compile the code for module
  198. use and turn off stack limit checking. There is no problem with stack limit
  199. checking off as an address exception will occur if the stack grows below the
  200. stack end.
  201.  
  202.  
  203.  
  204. Technical Details
  205. -----------------
  206.  
  207. C requires two values, lying about in an accessible place, which indicate
  208. where the static data lies. Two constants, one for the program, and one for
  209. the shared library. The location for these was chosen to be at the end of
  210. the stack. In diagram form the stack looks like this:
  211.  
  212. High memory
  213.         Stack bottom            |
  214.         Start of stack data     |zzzzzzz
  215.                                 |zzzzzzzz
  216.  
  217.                 .
  218.                 .
  219.                 .
  220.                                 |zzzzz
  221.                                 |zzzzzzz
  222.         Stack pointer           |zzzz
  223.                                 |
  224.                                 |
  225.                 .
  226.                 .
  227.                 .
  228.                                 |
  229.                                 |
  230.         Stack limit             |
  231.                                 |
  232.                                 |
  233.                 .
  234.                 .
  235.                 .
  236.                                 | Static data
  237.         End of stack            | offsets here          (This is at a 1MByte boundary)
  238. Low memory
  239.  
  240. For the SVC stack the end of the stack is at a 1MByte boundary. For the
  241. procedure call standard, Stack pointer is r13, Stack limit is r10 and is a
  242. fixed distance above the end of the stack. So, reading through asm.Interface
  243. we see first the registers being alocated names (r0..r15, a1-a4, v1-v6, sl,
  244. fp, ip, sp, lr and pc), a couple of constants being defined, these
  245. correspond to the C and V bit in the program counter. Next some necessary
  246. values are imported. In amoungst these are the fsentry functions written in
  247. C. Exported from this piece of assembler are the entry points which can be
  248. passed to FileSwitch. These pack up the parameters passed in by FileSwitch,
  249. and set everything up for C. The area directive is there to identify what
  250. sort of area this is. Now comes the code. The exported entry points come
  251. first. These load r8 with a constant specific to the individual entry point
  252. then call the common 'set everything up for C' code. r8 is not used by any
  253. fsentry, and so is safe to use. fsentry_common establishes the environment
  254. for C to work in. First, all the registers which may hold a parameter and
  255. the the other registers which are going to be corrupted are pushed. This
  256. establishes a structure, held on the stack, which can be passed to the
  257. relevant fsentry. The stack end is then calculated (round down to a multiple
  258. of 1MByte), the old static data offsets are saved into registers r4 and r5,
  259. which remain unchanged over a procedure call, and the new values obtained
  260. from the filing system module's private workspace value (passed in in r12)
  261. and stored at the stack end. The next instruction (a DCD) is implemented
  262. this way to ensure the linker can fill in _Lib$Reloc$Off$DP, which is the
  263. magic difference between the stack end and the stack limit (read up about
  264. the ARM Procedure Call Standard in the PRM). The stack pointer is stored in
  265. r0 (a1) as the parameter to the functions. MOV lr, pc establishes the return
  266. address and the ADD pc, pc, r8 branches into the branch table at the end to
  267. call the relevant function. The next DCD moves the stack limit down to the
  268. stack end and the old offsets are restored from r4 and r5 (v1 and v2). r8
  269. holds the returned value temporarily whilst the actual returned values are
  270. extracted from the stack. If r8 wasn't 0 (an error was returned) then it is
  271. moved back to r0. If an error was returned the V bit is set and if r1 as
  272. picked off the stack was 0 then the C bit is set. These set the flags as
  273. required from a fsentry. r8 is finaly restored from the stack and the
  274. program returns to FileSwitch.
  275.  
  276.